package com.mofum.scope.spring.web;

import com.mofum.scope.annotation.service.parser.TableScopeParser;
import com.mofum.scope.common.annotation.metadata.service.MColumnScope;
import com.mofum.scope.common.annotation.metadata.service.MTableScope;
import com.mofum.scope.common.model.Parameter;
import com.mofum.scope.common.model.Scope;
import com.mofum.scope.common.utils.ParentFieldUtils;
import com.mofum.scope.spring.web.constant.Constant;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 抽象的权限范围列切面
 *
 * @author yuyang@qxy37.com
 * @since 2019-03-20
 **/
public abstract class AbstractColumnAspectJ extends AbstractAspect {

    @Around("config()")
    public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
        try {

            Object[] args = joinPoint.getArgs();

            if (args != null) {
                Signature signature = joinPoint.getSignature();
                MethodSignature methodSignature = (MethodSignature) signature;
                String[] names = methodSignature.getParameterNames();

                TableScopeParser scopeParser = new TableScopeParser();

                Map<Type, MTableScope> typeMTableScopeMap = scopeParser.parseType(joinPoint.getTarget().getClass());

                MTableScope mTableScope = typeMTableScopeMap.get(joinPoint.getTarget().getClass());


                if (mTableScope == null || mTableScope.getColumns() == null || mTableScope.getColumns().length == 0) {
                    return joinPoint.proceed(args);
                }

                Object[] newParams = new Object[args.length];

                for (int i = 0; i < args.length; i++) {
                    Parameter parameter = new Parameter(i, names[i], args[i]);
                    processParameter(parameter, mTableScope, true);
                    newParams[i] = parameter.getValue();
                }

                try {
                    return joinPoint.proceed(newParams);
                } catch (Throwable throwable) {
                    throw new RuntimeException(throwable.getMessage(), throwable);
                }

            } else {
                return joinPoint.proceed(args);
            }

        } catch (Throwable e) {
            getThrowableHandler().handler(e);
        }

        return null;
    }

    private void processParameter(Parameter parameter, MTableScope mTableScope, boolean eachNext) {

        if (parameter == null) {
            return;
        }

        Object object = parameter.getValue();

        //为空就不进行后续操作
        if (object == null) {
            return;
        }

        if (!(object instanceof List)) {
            Field field = null;
            field = ParentFieldUtils.getFieldByName(Constant.SCOPE_SCOPES, object.getClass());
            if (field != null && eachNext) {

                Object data = null;
                try {
                    field.setAccessible(true);
                    data = field.get(object);
                    field.setAccessible(false);
                } catch (IllegalAccessException e) {
                    data = null;
                }

                Parameter tempParameter = new Parameter(0, Constant.SCOPE_SCOPES, data);

                processParameter(tempParameter, mTableScope, false);

                try {
                    field.setAccessible(true);
                    field.set(object, tempParameter.getValue());
                    field.setAccessible(false);
                } catch (IllegalAccessException e) {
                    try {
                        field.set(object, null);
                    } catch (IllegalAccessException e1) {
                    }
                }
            }
            return;
        }


        //参数 是 权限范围字段
        if (parameter.getName().equals(Constant.SCOPE_SCOPES)) {

            List<Object> scopes = (List<Object>) object;

            List<Scope> result = new ArrayList<>();

            for (Object scope : scopes) {

                //不是Scope就跳过
                if (!(scope instanceof Scope)) {
                    continue;
                }

                if (scope == null) {
                    continue;
                }
                Scope temp = (Scope) scope;


                if (temp.getType() == null) {
                    temp.setType("");
                }

                MColumnScope columnScope = queryScopeByType(temp.getType(), mTableScope.getColumns());

                if (columnScope == null) {
                    continue;
                }

                //类型一致，就设置表名和列名
                temp.setType(columnScope.getType());
                temp.setTableName(columnScope.getTableName());
                temp.setColumn(columnScope.getName());

                result.add(temp);
            }

            parameter.setValue(result);

        }

    }

    /**
     * 根据类型查询范围
     *
     * @param type    类型
     * @param columns 类型字段
     * @return
     */
    private MColumnScope queryScopeByType(String type, MColumnScope[] columns) {

        String compareType = type == null ? "" : type;

        for (MColumnScope columnScope : columns) {

            String cType = columnScope.getType() == null ? "" : columnScope.getType();

            String name = columnScope.getName();

            if (name == null) {
                continue;
            }

            if (cType.equals(compareType)) {
                return columnScope;
            }

        }
        return null;
    }
}
